from fastapi import FastAPI, UploadFile, File, HTTPException, Request, Form
from fastapi.responses import FileResponse
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
import os
import shutil
import time
from pathlib import Path
from typing import Optional
from file2wav import convert_to_wav


class ConversionParams(BaseModel):
    segment_convert: bool = False
    start_time: str = "0:00:00"
    end_time: str = "0:00:01"


def create_app() -> FastAPI:
    """创建并配置FastAPI应用"""
    app = FastAPI(
        title="音频/视频转WAV API",
        description="使用FFmpeg将上传的音频或视频文件转换为WAV格式",
        version="1.0.0"
    )
    
    # 允许跨域请求
    app.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],  # 在生产环境中应该设置具体的源
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )
    
    # 创建上传和输出目录
    UPLOAD_DIR = Path("uploads")
    OUTPUT_DIR = Path("output")
    UPLOAD_DIR.mkdir(exist_ok=True)
    OUTPUT_DIR.mkdir(exist_ok=True)
    
    @app.post("/convert-to-wav/")
    async def convert_audio_to_wav(
        request: Request,
        file: UploadFile = File(...),
        segment_convert: bool = Form(False),
        start_time: str = Form("0:00:00"),
        end_time: str = Form("0:00:01")
    ):
        """
        将上传的音频或视频文件转换为WAV格式

        参数:
            request: FastAPI请求对象，用于获取基础URL
            file: 上传的音频或视频文件
            segment_convert: 是否按时段转换，默认为False
            start_time: 开始时段，格式为"HH:MM:SS"，默认为"0:00:00"
            end_time: 结束时段，格式为"HH:MM:SS"，默认为"0:00:01"

        返回:
            dict: 包含转换结果和下载链接的信息
        """
        # 检查文件类型
        if not file.content_type.startswith(("audio/", "video/")):
            raise HTTPException(
                status_code=400,
                detail="不支持的文件类型。请上传音频或视频文件。"
            )
        
        # 记录开始时间
        start_time_record = time.time()

        # 保存上传的文件
        input_path = UPLOAD_DIR / file.filename
        try:
            with open(input_path, "wb") as buffer:
                shutil.copyfileobj(file.file, buffer)
        except Exception as e:
            raise HTTPException(status_code=500, detail=f"保存文件失败: {str(e)}")

        try:
            # 转换文件
            output_filename = os.path.splitext(file.filename)[0] + ".wav"
            # 如果是时段转换，在文件名中添加时段信息
            if segment_convert:
                base_name = os.path.splitext(file.filename)[0]
                output_filename = f"{base_name}_{start_time.replace(':', 'min')}_to_{end_time.replace(':', 'min')}.wav"

            output_path = OUTPUT_DIR / output_filename
            convert_to_wav(
                str(input_path),
                str(output_path),
                segment_convert=segment_convert,
                start_time=start_time,
                end_time=end_time
            )

            # 计算转换时间
            conversion_time = round(time.time() - start_time_record, 2)

            # 构建完整的HTTP下载URL
            base_url = str(request.base_url).rstrip('/')
            download_url = f"{base_url}/download/{output_filename}"

            response_data = {
                "message": "文件转换成功",
                "original_filename": file.filename,
                "converted_filename": output_filename,
                "download_url": download_url,
                "conversion_time_seconds": conversion_time
            }

            # 如果启用了时段转换，添加时段信息
            if segment_convert:
                response_data.update({
                    "segment_convert": True,
                    "start_time": start_time,
                    "end_time": end_time
                })

            return response_data
        except Exception as e:
            raise HTTPException(status_code=500, detail=f"转换文件失败: {str(e)}")
        finally:
            # 删除上传的临时文件
            if os.path.exists(input_path):
                os.remove(input_path)
    
    @app.get("/download/{filename}")
    async def download_file(filename: str):
        """
        下载转换后的WAV文件
        
        参数:
            filename: 要下载的文件名
        
        返回:
            FileResponse: 转换后的WAV文件
        """
        file_path = OUTPUT_DIR / filename
        if not file_path.exists():
            raise HTTPException(status_code=404, detail="文件不存在")
        
        return FileResponse(
            path=str(file_path),
            media_type="audio/wav",
            filename=filename
        )
    
    @app.get("/")
    async def root():
        """根路径，返回API信息"""
        return {
            "message": "音频/视频转WAV API",
            "version": "1.0.0",
            "docs": "/docs"
        }
    
    return app
